package cc.huasky.demo.ircamerademo;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Color;
import android.graphics.SurfaceTexture;
import android.hardware.usb.UsbDevice;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.Log;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.Switch;

import com.arcsoft.face.AgeInfo;
import com.arcsoft.face.ErrorInfo;
import com.arcsoft.face.Face3DAngle;
import com.arcsoft.face.FaceEngine;
import com.arcsoft.face.FaceInfo;
import com.arcsoft.face.GenderInfo;
import com.arcsoft.face.LivenessInfo;
import com.arcsoft.face.LivenessParam;
import com.arcsoft.face.enums.DetectFaceOrientPriority;
import com.arcsoft.face.enums.DetectMode;
import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.ScreenUtils;
import com.blankj.utilcode.util.SizeUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.jiangdg.usbcamera.UVCCameraHelper;
import com.jiangdg.usbcamera.UVCCameraHelperIR;
import com.jiangdg.usbcamera.utils.FileUtils;
import com.out.outdevice.LedQrcodeCtrl;
import com.serenegiant.usb.CameraDialog;
import com.serenegiant.usb.USBMonitor;
import com.serenegiant.usb.UVCCamera;
import com.serenegiant.usb.common.AbstractUVCCameraHandler;
import com.serenegiant.usb.common.AbstractUVCCameraHandlerIR;
import com.serenegiant.usb.common.UVCCameraHandler;
import com.serenegiant.usb.common.UVCCameraHandlerIR;
import com.serenegiant.usb.widget.CameraViewInterface;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

public class MainActivity extends AppCompatActivity implements CameraDialog.CameraDialogParent , CameraViewInterface.Callback {


    private boolean DEBUG;
    @BindView(R.id.uIrCameraView)
    View uIrCameraView;
    @BindView(R.id.uRGBCameraView)
    View uRGBCameraView;
    @BindView(R.id.switchLight)
    Switch switchLight;
    @BindView(R.id.faceRectViewRGB)
    FaceRectView faceRectViewRGB;
    private CameraViewInterface mUVCCameraView;
    private CameraViewInterface mUVCCameraView2;
    private Handler handler = new Handler();
    private DrawHelper drawHelper;

    private int processMask = FaceEngine.ASF_AGE | FaceEngine.ASF_FACE3DANGLE | FaceEngine.ASF_GENDER;

    private Handler testHandler = new Handler();


    /**
     * 用于人脸检测的引擎
     */
    private FaceEngine faceEngine;
    private int afCode;
    private boolean IS_PROGRESS;
    private int activeCode;

    private FaceEngine flEngine;
    private int flCode;

    private boolean isRequest;
    private boolean isIrRequest;
    private String TAG = this.getClass().getSimpleName();
    private View mTextureView;
    private UVCCameraHandler rgbCameraHandler;
    private UVCCameraHandlerIR irCameraHandler;
    private UVCCameraHelper rgbCameraHelper;
    private UVCCameraHelperIR irCameraHelper;
    private USBMonitor mUSBMonitor;
    private Runnable runnable;
    private byte[] irFaceData;
    private boolean isIrPreview;
    private boolean isPreview;

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
//        testHandler.postDelayed(new Runnable() {
//            @Override
//            public void run() {
//                finish();
//            }
//        } , 3000);
        DEBUG = AppUtils.isAppDebug();
        activeEngine();
        initEngine();
//        mUSBMonitor = new USBMonitor(this, mOnDeviceConnectListener);

        initCameraRGB();
        initCameraIr();

//        requestPermission();
//
//        handler = new Handler();
//        runnable = new Runnable() {
//            @Override
//            public void run() {
//                if(rgbCameraHandler == null || irCameraHandler == null){
//                    return;
//                }
//                if (!rgbCameraHandler.isOpened() || !irCameraHandler.isOpened()) {
//                    requestPermission();
//                    handler.postDelayed(runnable, 500);
//                }
//            }
//        };
//        handler.postDelayed(runnable, 3000);


        switchLight.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    LedQrcodeCtrl.Led_LedFaceOn();
                } else {
                    LedQrcodeCtrl.Led_LedFaceOff();
                }
            }
        });


        Looper.getMainLooper().getQueue().addIdleHandler(new MessageQueue.IdleHandler() {
            @Override
            public boolean queueIdle() {
                drawHelper = new DrawHelper(mTextureView.getWidth(), mTextureView.getHeight(), mTextureView.getWidth(), mTextureView.getHeight(),
                        180, 1, true, true, true);
                return false;
            }
        });
    }


    private void initCameraRGB() {
//        mTextureView = uRGBCameraView;
//        mUVCCameraView = (CameraViewInterface) mTextureView;
//        rgbCameraHandler = UVCCameraHandler.createHandler(this, mUVCCameraView, UVCCamera.DEFAULT_PREVIEW_WIDTH,
//                UVCCamera.DEFAULT_PREVIEW_HEIGHT, 0.5f);
//        rgbCameraHandler.setOnPreViewResultListener(new AbstractUVCCameraHandler.OnPreViewResultListener() {
//            @Override
//            public void onPreviewResult(byte[] rgbNv21) {
//                analysisFace(rgbNv21);
//            }
//        });
        mUVCCameraView = (CameraViewInterface) uRGBCameraView;
        mTextureView = uRGBCameraView;
        rgbCameraHelper = new UVCCameraHelper();
//        rgbCameraHelper.setDefaultPreviewSize(UVCCamera.DEFAULT_PREVIEW_WIDTH , UVCCamera.DEFAULT_PREVIEW_HEIGHT);
        rgbCameraHelper.setDefaultFrameFormat(UVCCameraHelper.FRAME_FORMAT_MJPEG);
        rgbCameraHelper.initUSBMonitor(this , mUVCCameraView , listener);

        Log.d(TAG, "width: " + rgbCameraHelper.getPreviewWidth() + "   height: " + rgbCameraHelper.getPreviewHeight());
        rgbCameraHelper.setOnPreviewFrameListener(new AbstractUVCCameraHandler.OnPreViewResultListener() {
            @Override
            public void onPreviewResult(byte[] data) {
                analysisFace(data);
            }
        });
    }

    private void analysisFace(byte[] rgbNv21) {
        Log.d(TAG, "onPreviewResult: ");
        if (irFaceData == null) {
            return;
        }
        List<FaceInfo> faceInfoList = new ArrayList<>();
        int code = faceEngine.detectFaces(rgbNv21, UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, FaceEngine.CP_PAF_NV21, faceInfoList);
        Log.i("camera", "code=" + code);
        if (code == ErrorInfo.MOK && faceInfoList.size() > 0) {
            code = faceEngine.process(rgbNv21, UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, FaceEngine.CP_PAF_NV21, faceInfoList, processMask);
            Log.i("camera", "process code=" + code);
            int liveCode = flEngine.processIr(irFaceData, UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, FaceEngine.CP_PAF_NV21, faceInfoList, FaceEngine.ASF_IR_LIVENESS);

            if (code == ErrorInfo.MOK && liveCode == ErrorInfo.MOK) {
                IS_PROGRESS = true;
            } else {
                IS_PROGRESS = false;
            }
        } else {
            //无人脸时去掉人脸框
            if (faceRectViewRGB != null) {
                faceRectViewRGB.clearFaceInfo();
            }
        }

        List<AgeInfo> ageInfoList = new ArrayList<>();
        List<GenderInfo> genderInfoList = new ArrayList<>();
        List<Face3DAngle> face3DAngleList = new ArrayList<>();
        List<LivenessInfo> faceLivenessInfoList = new ArrayList<>();
        int ageCode = faceEngine.getAge(ageInfoList);
        int genderCode = faceEngine.getGender(genderInfoList);
        int face3DAngleCode = faceEngine.getFace3DAngle(face3DAngleList);
        int liveResult = flEngine.setLivenessParam(new LivenessParam(0.5f, 0.7f));
        int livenessCode = flEngine.getIrLiveness(faceLivenessInfoList);

        // 有其中一个的错误码不为ErrorInfo.MOK
        if ((ageCode | genderCode | face3DAngleCode | livenessCode) != ErrorInfo.MOK) {
            IS_PROGRESS = false;
        }

        Log.i("camera", "all code=0");
        if (faceRectViewRGB != null && drawHelper != null) {
            List<DrawInfo> drawInfoList = new ArrayList<>();
            for (int i = 0; i < faceInfoList.size(); i++) {
                drawInfoList.add(new DrawInfo(drawHelper.adjustRect(faceInfoList.get(i).getRect()), genderInfoList.get(i).getGender(), ageInfoList.get(i).getAge(), faceLivenessInfoList.get(i).getLiveness(), Color.GREEN, null));
            }
            //是否显示活体
            drawHelper.setShowAlive(true);
            //绘制人脸框
            drawHelper.draw(faceRectViewRGB, drawInfoList);

        }
    }


    private void initCameraIr() {

        mUVCCameraView2 = (CameraViewInterface) uIrCameraView;
        irCameraHelper = new UVCCameraHelperIR();
        irCameraHelper.setDefaultFrameFormat(UVCCameraHelperIR.FRAME_FORMAT_YUYV);
//        irCameraHelper.setDefaultPreviewSize(SizeUtils.dp2px(1) , SizeUtils.dp2px(1));
        Log.d(TAG, "IrWidth: " + irCameraHelper.getPreviewWidth() + "   irHeight:" + irCameraHelper.getPreviewHeight());
        irCameraHelper.initUSBMonitor(this , mUVCCameraView2 , irListener);
        irCameraHelper.setOnPreviewFrameListener(new AbstractUVCCameraHandlerIR.OnPreViewResultListener() {
            @Override
            public void onPreviewResult(byte[] data) {
                Log.d(TAG, "irCameraHelper: ");
                irFaceData = data;
            }
        });
    }


    private void activeEngine() {
        activeCode = FaceEngine.activeOnline(MainActivity.this, "6tgAyMy4zoDdB3Jk2nemZ1A5b6DZuWnTTRoaYGoYhp7d", "9g3wTHsWzukdHC5aeqRhyXfQykiUosma8qS2TR2xJ8fA");
        if (activeCode == ErrorInfo.MOK) {
            ToastUtils.showShort("激活成功");
        } else {
            ToastUtils.showShort("激活失败,错误码：" + activeCode);
        }
    }

    private void initEngine() {

        faceEngine = new FaceEngine();
        afCode = faceEngine.init(this, DetectMode.ASF_DETECT_MODE_VIDEO, DetectFaceOrientPriority.ASF_OP_0_ONLY,
                20, 10, FaceEngine.ASF_FACE_DETECT | FaceEngine.ASF_AGE | FaceEngine.ASF_FACE3DANGLE | FaceEngine.ASF_GENDER);

        flEngine = new FaceEngine();
        flCode = flEngine.init(this, DetectMode.ASF_DETECT_MODE_VIDEO, DetectFaceOrientPriority.ASF_OP_0_ONLY,
                20, 10, FaceEngine.ASF_IR_LIVENESS);

    }

//
//    private final USBMonitor.OnDeviceConnectListener mOnDeviceConnectListener = new USBMonitor.OnDeviceConnectListener() {
//        @Override
//        public void onAttach(final UsbDevice device) {
//            if (DEBUG) Log.v(TAG, "onAttach:");
//        }
//
//        @Override
//        public void onConnect(final UsbDevice device, final USBMonitor.UsbControlBlock ctrlBlock, final boolean createNew) {
//            //设备连接成功
//            if (DEBUG) Log.v(TAG, "onConnect:");
//            if (device.getProductName().equals("SS-WDR-200W")) {
//                rgbCameraHandler.open(ctrlBlock);
//                if (mUVCCameraView != null) {
//                    final SurfaceTexture st = mUVCCameraView.getSurfaceTexture();
//                    if (st != null) {
//                        rgbCameraHandler.startPreview(new Surface(st));
//                    }
//                }
//
//            } else if (device.getProductName().equals(" Camera VR")) {
//                irCameraHandler.open(ctrlBlock);
//                if (mUVCCameraView2 != null) {
//                    final SurfaceTexture st = mUVCCameraView2.getSurfaceTexture();
//                    if (st != null) {
//                        irCameraHandler.startPreview(new Surface(st));
//                    }
//                }
//            }
//        }
//
//        @Override
//        public void onDisconnect(final UsbDevice device, final USBMonitor.UsbControlBlock ctrlBlock) {
//            if (DEBUG) Log.v(TAG, "onDisconnect:");
//            if ((rgbCameraHandler != null) && !rgbCameraHandler.isEqual(device)) {
//                queueEvent(new Runnable() {
//                    @Override
//                    public void run() {
//                        rgbCameraHandler.close();
//                        if (mUVCCameraView != null && mUVCCameraView.getSurface() != null) {
//                            mUVCCameraView.getSurface().release();
//                            mUVCCameraView = null;
//                        }
//                    }
//                }, 0);
//            } else if ((irCameraHandler != null) && !irCameraHandler.isEqual(device)) {
//                queueEvent(new Runnable() {
//                    @Override
//                    public void run() {
//                        irCameraHandler.close();
//                        if (mUVCCameraView2.getSurface() != null) {
//                            mUVCCameraView2.getSurface().release();
//                            mUVCCameraView2 = null;
//                        }
//                    }
//                }, 0);
//            }
//        }
//
//        @Override
//        public void onDettach(final UsbDevice device) {
//            if (DEBUG) Log.v(TAG, "onDettach:");
//        }
//
//        @Override
//        public void onCancel(final UsbDevice device) {
//            if (DEBUG) Log.v(TAG, "onCancel:");
//        }
//    };


    private UVCCameraHelper.OnMyDevConnectListener listener = new UVCCameraHelper.OnMyDevConnectListener() {
        @Override
        public void onAttachDev(UsbDevice device) {
// request open permission
            if (!isRequest) {
                isRequest = true;
                if (rgbCameraHelper != null) {
                    rgbCameraHelper.requestPermission(0 , device);
                }
            }
        }

        @Override
        public void onDettachDev(UsbDevice device) {
            if (isRequest) {
                isRequest = false;
                rgbCameraHelper.closeCamera();
            }
        }

        @Override
        public void onConnectDev(UsbDevice device, boolean isConnected) {
            if (!isConnected) {
//                showShortMsg("fail to connect,please check resolution params");
                isPreview = false;
            } else {
                isPreview = true;
            }
        }

        @Override
        public void onDisConnectDev(UsbDevice device) {

        }
    };


    private UVCCameraHelperIR.OnMyDevConnectListener irListener = new UVCCameraHelperIR.OnMyDevConnectListener() {
        @Override
        public void onAttachDev(UsbDevice device) {
            if (!isIrRequest) {
                isIrRequest = true;
                if (irCameraHelper != null) {
                    irCameraHelper.requestPermission(1 , device);
                }
            }
        }

        @Override
        public void onDettachDev(UsbDevice device) {
            if (isIrRequest) {
                isRequest = false;
                irCameraHelper.closeCamera();
            }
        }

        @Override
        public void onConnectDev(UsbDevice device, boolean isConnected) {
            if (!isConnected) {
//                showShortMsg("fail to connect,please check resolution params");
                isIrPreview = false;
            } else {
                isIrPreview = true;
            }
        }

        @Override
        public void onDisConnectDev(UsbDevice device) {

        }
    };
    @Override
    protected void onStart() {
        super.onStart();

        if (rgbCameraHelper != null) {
            rgbCameraHelper.registerUSB();
        }


        if(irCameraHelper != null){
            irCameraHelper.registerUSB();
        }
    }




    @Override
    protected void onStop() {
        super.onStop();
//        if (rgbCameraHandler != null) {
//            rgbCameraHandler.close();
//        }
//        if (mUVCCameraView != null) {
//            mUVCCameraView.onPause();
//        }
//
//        if (irCameraHandler != null) {
//            irCameraHandler.close();
//        }
//
//        if (mUVCCameraView2 != null) {
//            mUVCCameraView2.onPause();
//        }
//
//        if (mUSBMonitor != null) {
//            mUSBMonitor.unregister();//usb管理器解绑
//        }
        if(rgbCameraHelper != null){
            rgbCameraHelper.unregisterUSB();
        }

        if(irCameraHelper != null){
            irCameraHelper.unregisterUSB();
        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
//        if (rgbCameraHandler != null) {
//            rgbCameraHandler.release();
//            rgbCameraHandler = null;
//        }
//
//        if (irCameraHandler != null) {
//            irCameraHandler.release();
//            irCameraHandler = null;
//        }
//        if (mUSBMonitor != null) {
//            mUSBMonitor.destroy();
//            mUSBMonitor = null;
//        }

        // step.4 release uvc camera resources
        if (rgbCameraHelper != null) {
            rgbCameraHelper.closeCamera();
            FileUtils.releaseFile();
            rgbCameraHelper.release();
        }

        if(irCameraHelper != null){
            irCameraHelper.closeCamera();
            FileUtils.releaseFile();
            irCameraHelper.release();
        }
        if(afCode == ErrorInfo.MOK && faceEngine != null){
            synchronized (faceEngine) {
                int faceUnInitCode = faceEngine.unInit();
                Log.i(TAG, "unInitEngine: " + faceUnInitCode);
            }
        }

        if (flCode == ErrorInfo.MOK && flEngine != null) {
            synchronized (flEngine) {
                int flUnInitCode = flEngine.unInit();
                Log.i(TAG, "unInitEngine: " + flUnInitCode);
            }
        }
    }


    @Override
    public USBMonitor getUSBMonitor() {
        return rgbCameraHelper.getUSBMonitor();
    }

    @Override
    public void onDialogResult(boolean canceled) {

    }

    @Override
    public void onSurfaceCreated(CameraViewInterface view, Surface surface) {
        if (!isIrPreview && irCameraHelper.isCameraOpened()) {
            irCameraHelper.startPreview(mUVCCameraView2);
            isIrPreview = true;
        }

        if(!isPreview && rgbCameraHelper.isCameraOpened()){
            rgbCameraHelper.startPreview(mUVCCameraView);
            isPreview = true;
        }
    }

    @Override
    public void onSurfaceChanged(CameraViewInterface view, Surface surface, int width, int height) {

    }

    @Override
    public void onSurfaceDestroy(CameraViewInterface view, Surface surface) {
        if (isPreview && rgbCameraHelper.isCameraOpened()) {
            rgbCameraHelper.stopPreview();
            isPreview = false;
        }

        if(isIrPreview && irCameraHelper.isCameraOpened()){
            irCameraHelper.stopPreview();
            isIrPreview = false;
        }
    }
}